package com.rad.net.protocol.android;

import android.content.Context;
import android.text.TextUtils;

import com.rad.net.protocol.android.cache.CacheStrategy;
import com.rad.net.protocol.android.cache.DefaultCacheStrategy;
import com.rad.net.protocol.android.decoder.Decoder;
import com.rad.net.protocol.android.decoder.DefaultJsonDecoder;
import com.rad.net.protocol.android.encoder.DefaultEncoder;
import com.rad.net.protocol.android.encoder.Encoder;
import com.rad.net.protocol.android.http.DefaultHttpTransporter;
import com.rad.net.protocol.android.http.HttpTransporter;
import com.rad.net.protocol.android.http.Request;
import com.rad.net.protocol.android.http.Response;
import com.rad.net.protocol.android.utils.CfgUtils;
import com.rad.net.protocol.android.utils.LogUtils;
import com.rad.net.protocol.common.cmd.BaseCmd;
import com.rad.net.protocol.common.extra.CacheInterface;
import com.rad.net.protocol.common.extra.Http304Interface;
import com.rad.net.protocol.common.result.ErrorResult;


/** 
 * 类说明：   联网逻辑控制器
 * @author  xinhui.cheng
 * @date    2014-8-25
 * @version 1.0
 */
public class NetController {

	private static final String TAG = NetController.class.getSimpleName();
	
	private static final int RETRY_COUNT = 1;
	private static String sResultPkg;
	private static String sUrlHost;
	private static String sSecretKey;
	
	private HttpTransporter mHttpTransporter;
	private Encoder mEncoder;
	private Decoder mDecoder;
	private CacheStrategy mCacheStrategy;
	private Context mContext;
	
	private int mRetryCount = RETRY_COUNT;
	
	public NetController(Context context){
		mContext = context;
	}
	
	/**
	 * 设置联网逻辑默认参数
	 * @param resultPkg 返回结果类所在的包名
	 * @param urlHost 联网的主机地址，不包含需要自动拼接的参数
	 * @param secretKey 联网加密密钥
	 */
	public static void setDefaultParams(String resultPkg,String urlHost,String secretKey){
		sResultPkg = resultPkg;
		sUrlHost = urlHost;
		sSecretKey = secretKey;
	}
	
	/**
	 * 设置联网处理器 {@link HttpTransporter} 对象
	 * @param httpTransporter  {@link HttpTransporter} 对象
	 */
	public void setHttpTransporter(HttpTransporter httpTransporter){
		mHttpTransporter = httpTransporter;
	}

	/**
	 * 设置编码器 {@link Encoder} 对象
	 * 
	 * @param encoder
	 */
	public void setEncoder(Encoder encoder) {
		mEncoder = encoder;
	}

	/**
	 * 设置解码器 {@link Decoder} 对象
	 * 
	 * @param decoder
	 */
	public void setDecoder(Decoder decoder) {
		mDecoder = decoder;
	}

	/**
	 * 设置缓存策略
	 * 
	 * @param cacheStrategy
	 */
	public void setCacheStrategy(CacheStrategy cacheStrategy) {
		mCacheStrategy = cacheStrategy;
	}
	
	private void check(BaseCmd cmd){
		if(mHttpTransporter == null){
			mHttpTransporter = new DefaultHttpTransporter(mContext);
		}
		if(mDecoder == null){
			mDecoder = new DefaultJsonDecoder(sResultPkg);
		}
		if(mEncoder == null){
			mEncoder = new DefaultEncoder(sSecretKey);
		}
		if(mCacheStrategy == null){
			mCacheStrategy = new DefaultCacheStrategy();
		}
		if(TextUtils.isEmpty(cmd.getServerUrl())){
			cmd.setServerUrl(sUrlHost);
		}
		if(TextUtils.isEmpty(cmd.getAndroid_id())){
			cmd.setAndroid_id(CfgUtils.getAndroidId(mContext));
		}
		if(TextUtils.isEmpty(cmd.getChannel())){
			cmd.setChannel(CfgUtils.getChannelNumber(mContext));
		}
		if(TextUtils.isEmpty(cmd.getPackageName())){
			cmd.setPackageName(mContext.getPackageName());
		}
		if(TextUtils.isEmpty(cmd.getVersionName())){
			cmd.setVersionName(CfgUtils.getVersionName(mContext));
		}
		if(cmd.getVersionCode() ==0){
			cmd.setVersionCode(CfgUtils.getVersionCode(mContext));
		}
		
	}
	
	/**
	 * 开始网络请求。
	 * @param cmd
	 * @return 成功则返回目标结果，失败返回{@link ErrorResult};
	 */
	public Object startRequest(BaseCmd cmd){
		if(cmd == null){
			return getErrorResult("cmd is null");
		}
		check(cmd);
		String cacheKey = "";
		long cacheTime = 0;
		if(cmd instanceof CacheInterface){
			CacheInterface cache = (CacheInterface) cmd;
			cacheKey = cache.getCacheKey();
			cacheTime = cache.getCacheTime();
		}
				
		Object result = mCacheStrategy.getCache(cacheKey, false);
		if(result == null){
			Request request = mEncoder.encode(cmd);
			Response response = mHttpTransporter.sendRequest(request);
			if(response == null){
				return getErrorResult("");
			}
			int stateCode = response.getStatusCode();
			LogUtils.i(TAG, "response startCode :"+stateCode);
			if(stateCode != 200){
				//结果未改变
				if(stateCode == 304){
					//先强制获取缓存
					result = mCacheStrategy.getCache(cacheKey, true);
					if(result != null){
						mCacheStrategy.refresh(cacheKey, cacheTime);
						LogUtils.i(TAG, "startCode 304, force use cache~~!");
						return result;
					} else {
						return http304Retry(cmd);
					}
				} else {
					return getErrorResult("");
				}
			} else {
				result = mDecoder.decode(response);
				if(result == null){
					LogUtils.i(TAG, "decode error!");
					return getErrorResult("decode error");
				} else if(!(result instanceof ErrorResult)){
					mCacheStrategy.putCache(cacheKey, result, cacheTime);
				}
				return result;
			}
		} else {
			LogUtils.i(TAG, "use cache~~!");
			return result;
		}
	}

	
	private Object http304Retry(BaseCmd cmd){
		BaseCmd retryCmd = null;
		if(cmd instanceof Http304Interface){
			Http304Interface http304 = (Http304Interface) cmd;
			retryCmd = http304.getRebornCmd();
		}
		
		if(retryCmd == null){
			return getErrorResult("Http304Interface.getRebornCmd() is null");
		} else {
			if(mRetryCount <= 0){
				mRetryCount = RETRY_COUNT;
				return getErrorResult("304 retry not result");
			} else {
				mRetryCount -- ;
				return startRequest(retryCmd);
			}
		}
	}
	
	private ErrorResult getErrorResult(String detail){
		ErrorResult result = new ErrorResult();
		result.setType("error");
		result.setError(-111111111);
		result.setDetail(detail);
		return result;
	}
	
}
